#pragma  once
#include <map>
#include <list>
#include "InstructionMgr.h"
#include "IByteStreamReader.h"
#include "IExecDisasmRule.h"
#include "OpCodeMap.h"

class __declspec(dllexport) DisasmExecMgr 
{
    CONTEXT m_ct;
    InstructionManager* m_pInstructionMgr;
    std::map<DWORD, DWORD> m_memMap;
    IByteStreamReader*  m_debugProcessReader;
    IExecDisasmRule*     m_execRule;
    typedef bool (DisasmExecMgr::*PFCOMMAND)(CString);
    // Commands that can be executed
    std::map<CString, PFCOMMAND> m_commands;
    DWORD m_result;
    std::list<CString> m_instructionStrArray;
    DWORD m_segFS;
    int m_iCallLevel;

public:
    DisasmExecMgr(CONTEXT ct, InstructionManager* pInstructionMgr, IByteStreamReader* pDebugeeProcessReader);
    ~DisasmExecMgr();
    bool StartExecute();
    void  AppendParameter(DWORD param);
    void* GetRetVal();
    void SetExecRule(IExecDisasmRule* execRule);
    void SetFS(DWORD segFS)
    {
        m_segFS = segFS;
    }
    DWORD GetFS()
    {
        return m_segFS;
    }
private:
    bool Execute(CString disasmStr);
    bool GetDescOperand(CString opCodeStr, CString & descOperand);
    bool GetSrcOperand(CString opCodeStr, CString & srcOperand);
    bool GetSrcOperand2(CString opCodeStr, CString & srcOperand1, CString & srcOperand2);
    bool GetOperand(CString opCodeStr, CString & operand);
    void InitCommands();
    DWORD GetSrcDWFromStr(CString opCodeStr);
    DWORD PraseStr(CString opCodeStr);
    DWORD GetRealValue(CString opCodeStr);
    bool SetRegValue(CString opCodeStr, DWORD dSrcValue);
    DWORD GetValueFromAddress(CString opCodeStr, DWORD effectAddr);
    bool SetValueToAddress(DWORD address, DWORD value, int iByteType);
    void SetResult(DWORD result);
    DWORD GetResult();
    void SetCF(bool result);// a lot of functions needs call this
    bool GetCF();
    bool GetDF();

protected:
    // Commands
    bool DoADD(CString args);
    bool DoAND(CString args);
    bool DoCMP(CString args);
    bool DoCALL(CString args);
    bool DoDEC(CString args);
    bool DoDIV(CString args);
    bool DoINC(CString args);
    bool DoJA(CString args);
    bool DoJAE(CString args);
    bool DoJB(CString args);
    bool DoJBE(CString args);
    bool DoJE(CString args);
    bool DoJMP(CString args);
    bool DoJNE(CString args);
    bool DoLEA(CString args);
    bool DoMOV(CString args);
    bool DoMOVZX(CString args);
    bool DoNEG(CString args);
    bool DoNOT(CString args);
    bool DoOR(CString args);
    bool DoPOP(CString args);
    bool DoPUSH(CString args);
    bool DoRET(CString args);
    bool DoROL(CString args);
    bool DoROR(CString args);
    bool DoSHL(CString args);
    bool DoSHR(CString args);
    bool DoSTI(CString args);
    bool DoSTO(CString args);
    bool DoSUB(CString args);
    bool DoSBB(CString args);
    bool DoTEST(CString args);
    bool DoXOR(CString args);
    bool DoXCHG(CString args);
    bool DoSETNE(CString args);
    bool DoSETE(CString args);
    bool DoSAL(CString args);
    bool DoSTC(CString args);
    bool DoREP(CString args);
    bool DoSTOS(CString args);
    bool DoIMUL(CString args);
    bool DoCMPXCHG(CString args);   
    bool DoInterrupt(CString args);   
};